package cn.lg.soar.common.data.dict;

import java.io.Serializable;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 字典类接口
 * @author luguoxiang
 * 开源项目：https://gitee.com/lgx1992/lg-soar 求star！请给我star！请帮我点个star！
 */
public interface IDict<V> {

    /**
     * 字典值
     * @return
     */
    V getValue();

    /**
     * 字典标签
     * @return
     */
    String getLabel();

    /**
     * 值比较
     * @param value
     * @return
     */
    default boolean eq(V value) {
        return this.getValue().equals(value);
    }

    /**
     * 转成 map<value, label>
     * @param dicts
     * @param <V>
     * @return
     */
    static <V> Map<V, String> toMap(Collection<? extends IDict<V>> dicts) {
        if (dicts == null || dicts.isEmpty()) {
            return Collections.emptyMap();
        }
        return dicts.stream().collect(Collectors.toMap(IDict::getValue, IDict::getLabel));
    }

    /**
     * 转成 map<value, label>
     * @param dicts
     * @param <V>
     * @return
     */
    static <V> Map<V, String> toMap(IDict<V> ...dicts) {
        if (dicts == null || dicts.length == 0) {
            return Collections.emptyMap();
        }
        Map<V, String> map = new HashMap<>(dicts.length);
        for (IDict<V> dict : dicts) {
            map.put(dict.getValue(), dict.getLabel());
        }
        return map;
    }

    /**
     * 转成 map<label, value>
     * @param dicts
     * @param <V>
     * @return
     */
    static <V> Map<String, V> toLabelValueMap(Collection<? extends IDict<V>> dicts) {
        if (dicts == null || dicts.isEmpty()) {
            return Collections.emptyMap();
        }
        return dicts.stream().collect(Collectors.toMap(IDict::getLabel, IDict::getValue));
    }

    /**
     * 转成 map<label, value>
     * @param dicts
     * @param <V>
     * @return
     */
    static <V> Map<String, V> toLabelValueMap(IDict<V> ...dicts) {
        if (dicts == null || dicts.length == 0) {
            return Collections.emptyMap();
        }
        Map<String, V> map = new HashMap<>(dicts.length);
        for (IDict<V> dict : dicts) {
            map.put(dict.getLabel(), dict.getValue());
        }
        return map;
    }

    /**
     * 检查枚举值是否重复
     * @param enums
     * @param <T>
     */
    static <T extends Serializable>void checkRepeatValue(IDict<T>[] enums) {
        Map<T, Boolean> map = new HashMap<>(enums.length);
        for (IDict<T> e : enums) {
            T value = e.getValue();
            if (map.containsKey(value)) {
                throw new RuntimeException("枚举值重复，类：" + e.getClass().getName() + "，重复值：" + value);
            }
            map.put(value, true);
        }
    }

    /**
     * 根据值获取枚举实例
     * @param enumClass
     * @param value
     * @return
     * @param <V>
     * @param <T>
     */
    static <V, T extends IDict<V>>T valueOf(Class<T> enumClass, V value) {
        T[] enumConstants = enumClass.getEnumConstants();
        for (T enumConstant : enumConstants) {
            if (Objects.equals(enumConstant.getValue(), value)) {
                return enumConstant;
            }
        }
        throw new RuntimeException("未知类型");
    }

    /**
     * 根据标签名获取枚举实例
     * @param enumClass
     * @param label
     * @return
     * @param <V>
     * @param <T>
     */
    static <T extends IDict<?>>T valueOfLabel(Class<T> enumClass, String label) {
        T[] enumConstants = enumClass.getEnumConstants();
        for (T enumConstant : enumConstants) {
            if (Objects.equals(enumConstant.getLabel(), label)) {
                return enumConstant;
            }
        }
        throw new RuntimeException("未知类型");
    }

}
